#include "../log_system/log_system.h"

//性能压力测试
void bench(const std::string& loggerName, size_t thrCnt, size_t msgCnt, size_t msgLen)
{
    //1.获取日志器
    log_system::Logger::ptr logger = log_system::getLogger(loggerName);
    if(logger.get() == nullptr)
    {
        return;
    }

    std::cout << "测试日志:" << msgCnt << "条，总大小:" << (msgCnt * msgLen) / 1024 << "KB\n";
    //2.组织指定长度的日志消息
    std::string msg(msgLen - 1, 'A');//留一位给'\n'
    
    //3.创建指定数量的线程
    std::vector<std::thread> threads;

    //各个线程最终耗时统计
    std::vector<double> costArray(thrCnt);
    
    //各个线程要输出的日志数量
    size_t msg_per_thr = msgCnt / thrCnt;
    std::vector<size_t> msgCntPerThreads(thrCnt, msg_per_thr);

    //无法均分的日志，尽量均匀分配到各个线程
    size_t adjustCnt = msgCnt % thrCnt;
    for(size_t i = 0; i < adjustCnt; ++i)
    {
        msgCntPerThreads[i]++;
    }


    for(size_t i = 0; i < thrCnt; ++i)
    {
        threads.emplace_back([&, i](){
            //4.线程函数内部开始计时
            auto start = std::chrono::high_resolution_clock::now();
            
            //5.开始循环写日志
            for(size_t j = 0; j < msgCntPerThreads[i]; ++j)
            {
                logger->fatalLog("%s", msg.c_str());
            }

            //6.线程函数内部结束计时
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost = end - start;

            //记录单个线程的耗时
            costArray[i] = cost.count();

            std::cout << "线程" << i << ": " << "\t输出数量:" << msgCntPerThreads[i] << ", 耗时:" << cost.count() << "s" << std::endl;
        });
    }

    //确保线程都退出
    for(size_t i = 0; i < thrCnt; ++i)
    {
        threads[i].join();
    }

    //7.计算总耗时：多线程中，每个线程都会耗费时间，但是多线程是并发处理的，故耗时最高的即为总耗时
    double maxCost = costArray[0];
    for(size_t i = 1; i < thrCnt; ++i)
        maxCost = maxCost < costArray[i] ? costArray[i] : maxCost;
    
    size_t msg_per_sec = msgCnt / maxCost;
    size_t size_per_sec = (msgCnt * msgLen) / (maxCost * 1024);

    //8.进行输出打印
    std::cout << "\t总耗时" << maxCost << "s\n";
    std::cout << "\t每秒输出日志数量:" << msg_per_sec << "条\n";
    std::cout << "\t每秒输出日志大小:" << size_per_sec << "KB\n";
}

//同步线程测试
void sync_bench(size_t thrCnt, size_t msgCnt = 5000000, size_t msgLen = 100)
{
    std::cout << "同步" << (thrCnt == 1 ? "单线程" : ("多线程" + std::to_string(thrCnt))) << "测试:" << std::endl;
    std::unique_ptr<log_system::LoggerBuilder> builder(new log_system::GlobalLoggerBuilder());
    builder->buildLoggerName("sync_logger");
    builder->buildFormatter("%m%n");
    builder->buildLoggerType(log_system::LoggerType::LOGGER_SYNC);
    builder->buildSink<log_system::FileSink>("./log/sync.log");
    log_system::Logger::ptr logger = builder->build();
    bench(logger->name(), thrCnt, msgCnt, msgLen);
}

//异步线程测试
void async_bench(size_t thrCnt, size_t msgCnt = 5000000, size_t msgLen = 100)
{
    std::cout << "异步" << (thrCnt == 1 ? "单线程" : ("多线程" + std::to_string(thrCnt))) << "测试:" << std::endl;

    std::unique_ptr<log_system::LoggerBuilder> builder(new log_system::GlobalLoggerBuilder());
    builder->buildLoggerName("sync_logger");
    builder->buildFormatter("%m%n");
    builder->buildLoggerType(log_system::LoggerType::LOGGER_ASYNC);
    builder->enableUnsafeAsync();//非安全模式，将实际落地时间排除在外
    // std::cout << "安全模式下:\n";
    builder->buildSink<log_system::FileSink>("./log/async.log");
    log_system::Logger::ptr logger = builder->build();
    bench(logger->name(), thrCnt, msgCnt, msgLen);
}

int main()
{
    sync_bench(1);
    // sync_bench(3);
    // sync_bench(10);
    // sync_bench(20);

    // async_bench(1);
    // async_bench(3);
    // async_bench(10);
    // async_bench(20);
    return 0;
}